<?php
/**
 * 通用函数文件
 * 州弟医院信息系统 - 州弟学安全
 */

// 引入配置文件
require_once 'config.php';

/**
 * 检查用户是否已登录
 * @return bool 是否已登录
 */
function isLoggedIn() {
    return isset($_SESSION['user_id']);
}

/**
 * 检查用户是否有特定角色
 * @param string $role 角色名称
 * @return bool 是否有此角色
 */
function hasRole($role) {
    if (!isLoggedIn()) {
        return false;
    }
    return $_SESSION['user_role'] == $role;
}

/**
 * 重定向到指定URL
 * @param string $url 目标URL
 */
function redirect($url) {
    header("Location: $url");
    exit();
}

/**
 * 检查是否为AJAX请求
 * @return bool 是否为AJAX请求
 */
function isAjaxRequest() {
    return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && 
        strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
}

/**
 * 生成随机字符串
 * @param int $length 长度
 * @return string 随机字符串
 */
function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $randomString;
}

/**
 * 格式化日期时间
 * @param string $datetime 日期时间字符串
 * @param string $format 格式
 * @return string 格式化后的日期时间
 */
function formatDateTime($datetime, $format = 'Y-m-d H:i:s') {
    $dt = new DateTime($datetime);
    return $dt->format($format);
}

/**
 * 获取用户信息
 * @param int $userId 用户ID
 * @return array|null 用户信息数组或null
 */
function getUserInfo($userId) {
    global $conn;
    
    $userId = (int)$userId;
    $sql = "SELECT * FROM users WHERE id = $userId";
    $result = $conn->query($sql);
    
    if ($result && $result->num_rows > 0) {
        return $result->fetch_assoc();
    }
    
    return null;
}

/**
 * 获取患者详细信息
 * @param int $patientId 患者ID
 * @return array|null 患者信息数组或null
 */
function getPatientInfo($patientId) {
    global $conn;
    
    $patientId = (int)$patientId;
    $sql = "SELECT p.*, u.username, u.email 
            FROM patients p 
            JOIN users u ON p.user_id = u.id 
            WHERE p.id = $patientId";
            
    $result = $conn->query($sql);
    
    if ($result && $result->num_rows > 0) {
        return $result->fetch_assoc();
    }
    
    return null;
}

/**
 * 获取医生详细信息
 * @param int $doctorId 医生ID
 * @return array|null 医生信息数组或null
 */
function getDoctorInfo($doctorId) {
    global $conn;
    
    $doctorId = (int)$doctorId;
    $sql = "SELECT d.*, u.username, u.email, dept.name as department_name 
            FROM doctors d 
            JOIN users u ON d.user_id = u.id 
            JOIN departments dept ON d.department_id = dept.id
            WHERE d.id = $doctorId";
            
    $result = $conn->query($sql);
    
    if ($result && $result->num_rows > 0) {
        return $result->fetch_assoc();
    }
    
    return null;
}

/**
 * 展示错误消息
 * @param string $message 错误消息
 * @return string HTML错误消息
 */
function showError($message) {
    return '<div class="alert alert-danger">' . $message . '</div>';
}

/**
 * 展示成功消息
 * @param string $message 成功消息
 * @return string HTML成功消息
 */
function showSuccess($message) {
    return '<div class="alert alert-success">' . $message . '</div>';
}

/**
 * 获取所有科室
 * @return array 科室列表
 */
function getAllDepartments() {
    global $conn;
    
    $departments = array();
    $sql = "SELECT * FROM departments ORDER BY name";
    $result = $conn->query($sql);
    
    if ($result && $result->num_rows > 0) {
        while ($row = $result->fetch_assoc()) {
            $departments[] = $row;
        }
    }
    
    return $departments;
}

/**
 * 获取指定科室的所有医生
 * @param int $departmentId 科室ID
 * @return array 医生列表
 */
function getDoctorsByDepartment($departmentId) {
    global $conn;
    
    $doctors = array();
    $departmentId = (int)$departmentId;
    
    $sql = "SELECT d.*, u.username 
            FROM doctors d 
            JOIN users u ON d.user_id = u.id 
            WHERE d.department_id = $departmentId 
            ORDER BY d.name";
            
    $result = $conn->query($sql);
    
    if ($result && $result->num_rows > 0) {
        while ($row = $result->fetch_assoc()) {
            $doctors[] = $row;
        }
    }
    
    return $doctors;
}

/**
 * 验证电子邮件格式
 * @param string $email 电子邮件地址
 * @return bool 是否为有效的电子邮件格式
 */
function isValidEmail($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

/**
 * 验证电话号码格式
 * @param string $phone 电话号码
 * @return bool 是否为有效的电话号码格式
 */
function isValidPhone($phone) {
    return preg_match('/^1[3-9]\d{9}$/', $phone);
}

/**
 * 验证身份证号格式
 * @param string $idCard 身份证号
 * @return bool 是否为有效的身份证号格式
 */
function isValidIdCard($idCard) {
    return preg_match('/^\d{17}[\dXx]$/', $idCard);
}

/**
 * 清理并净化输入数据
 * @param string $data 输入数据
 * @return string 净化后的数据
 */
function sanitizeInput($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}

/**
 * 获取医疗费用类别列表
 * 
 * @param bool $only_common 是否只获取常用类别
 * @return array 费用类别列表
 */
function getFeeCategories($only_common = false) {
    global $conn;
    
    $sql = "SELECT * FROM fee_categories";
    if ($only_common) {
        $sql .= " WHERE is_common = 1";
    }
    $sql .= " ORDER BY name";
    
    $result = $conn->query($sql);
    $categories = [];
    
    if ($result->num_rows > 0) {
        while($row = $result->fetch_assoc()) {
            $categories[] = $row;
        }
    }
    
    return $categories;
}

/**
 * 获取特定类别的费用项目
 * 
 * @param int $category_id 类别ID
 * @return array 费用项目列表
 */
function getFeeItemsByCategory($category_id) {
    global $conn;
    
    $stmt = $conn->prepare("SELECT * FROM fee_items WHERE category_id = ? ORDER BY name");
    $stmt->bind_param("i", $category_id);
    $stmt->execute();
    $result = $stmt->get_result();
    $items = [];
    
    if ($result->num_rows > 0) {
        while($row = $result->fetch_assoc()) {
            $items[] = $row;
        }
    }
    
    $stmt->close();
    return $items;
}

/**
 * 获取费用项目信息
 * 
 * @param int $item_id 费用项目ID
 * @return array|null 费用项目信息，不存在返回null
 */
function getFeeItem($item_id) {
    global $conn;
    
    $stmt = $conn->prepare("SELECT * FROM fee_items WHERE id = ?");
    $stmt->bind_param("i", $item_id);
    $stmt->execute();
    $result = $stmt->get_result();
    
    if ($result->num_rows > 0) {
        $item = $result->fetch_assoc();
        $stmt->close();
        return $item;
    }
    
    $stmt->close();
    return null;
}

/**
 * 获取所有医疗保险计划
 * 
 * @return array 医疗保险计划列表
 */
function getInsurancePlans() {
    global $conn;
    
    $sql = "SELECT * FROM insurance_plans ORDER BY name";
    $result = $conn->query($sql);
    $plans = [];
    
    if ($result->num_rows > 0) {
        while($row = $result->fetch_assoc()) {
            $plans[] = $row;
        }
    }
    
    return $plans;
}

/**
 * 获取患者的医保信息
 * 
 * @param int $patient_id 患者ID
 * @return array|null 患者医保信息，不存在返回null
 */
function getPatientInsurance($patient_id) {
    global $conn;
    
    $stmt = $conn->prepare("
        SELECT pi.*, ip.name as plan_name, ip.coverage_percentage 
        FROM patient_insurances pi
        JOIN insurance_plans ip ON pi.insurance_plan_id = ip.id
        WHERE pi.patient_id = ? AND pi.status = '有效' 
        AND (pi.valid_to IS NULL OR pi.valid_to >= CURDATE())
        ORDER BY pi.valid_from DESC LIMIT 1
    ");
    $stmt->bind_param("i", $patient_id);
    $stmt->execute();
    $result = $stmt->get_result();
    
    if ($result->num_rows > 0) {
        $insurance = $result->fetch_assoc();
        $stmt->close();
        return $insurance;
    }
    
    $stmt->close();
    return null;
}

/**
 * 生成医疗账单编号
 * 
 * @return string 账单编号
 */
function generateBillNumber() {
    $prefix = 'HB';
    $date = date('Ymd');
    $random = mt_rand(1000, 9999);
    return $prefix . $date . $random;
}

/**
 * 创建医疗账单
 * 
 * @param int $patient_id 患者ID
 * @param int|null $medical_record_id 医疗记录ID
 * @param int|null $doctor_id 医生ID
 * @param string|null $notes 备注
 * @return int|bool 成功返回账单ID，失败返回false
 */
function createMedicalBill($patient_id, $medical_record_id = null, $doctor_id = null, $notes = null) {
    global $conn;
    
    $bill_number = generateBillNumber();
    $created_by = $_SESSION['user_id'] ?? null;
    
    $stmt = $conn->prepare("
        INSERT INTO medical_bills 
        (bill_number, patient_id, medical_record_id, doctor_id, notes, created_by) 
        VALUES (?, ?, ?, ?, ?, ?)
    ");
    $stmt->bind_param("siiiis", $bill_number, $patient_id, $medical_record_id, $doctor_id, $notes, $created_by);
    
    if ($stmt->execute()) {
        $bill_id = $stmt->insert_id;
        $stmt->close();
        return $bill_id;
    }
    
    $stmt->close();
    return false;
}

/**
 * 添加账单项目
 * 
 * @param int $bill_id 账单ID
 * @param int $fee_item_id 费用项目ID
 * @param int $quantity 数量
 * @param float|null $unit_price 单价（为空则使用项目默认价格）
 * @param bool|null $insurance_covered 是否医保覆盖
 * @param int|null $doctor_id 执行医生ID
 * @param int|null $department_id 执行科室ID
 * @param string|null $notes 备注
 * @return bool 成功返回true，失败返回false
 */
function addBillItem($bill_id, $fee_item_id, $quantity = 1, $unit_price = null, $insurance_covered = null, $doctor_id = null, $department_id = null, $notes = null) {
    global $conn;
    
    // 获取费用项目信息
    $fee_item = getFeeItem($fee_item_id);
    if (!$fee_item) {
        return false;
    }
    
    // 如果未提供单价，使用项目默认价格
    if ($unit_price === null) {
        $unit_price = $fee_item['price'];
    }
    
    // 如果未指定是否医保覆盖，使用项目默认设置
    if ($insurance_covered === null) {
        $insurance_covered = $fee_item['is_medical_insurance'];
    }
    
    // 计算总价
    $total_price = $unit_price * $quantity;
    
    // 获取账单和患者信息
    $stmt = $conn->prepare("SELECT patient_id FROM medical_bills WHERE id = ?");
    $stmt->bind_param("i", $bill_id);
    $stmt->execute();
    $result = $stmt->get_result();
    
    if ($result->num_rows == 0) {
        $stmt->close();
        return false;
    }
    
    $bill = $result->fetch_assoc();
    $patient_id = $bill['patient_id'];
    $stmt->close();
    
    // 获取患者医保信息
    $insurance = getPatientInsurance($patient_id);
    
    // 计算医保金额和自付金额
    $insurance_amount = 0;
    $self_pay_amount = $total_price;
    
    if ($insurance_covered && $insurance) {
        $coverage_percentage = $insurance['coverage_percentage'];
        $insurance_amount = $total_price * ($coverage_percentage / 100);
        $self_pay_amount = $total_price - $insurance_amount;
    }
    
    // 添加账单项目
    $stmt = $conn->prepare("
        INSERT INTO medical_bill_items 
        (bill_id, fee_item_id, item_name, quantity, unit_price, total_price, 
         insurance_covered, insurance_amount, self_pay_amount, doctor_id, department_id, notes) 
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    ");
    
    $item_name = $fee_item['name'];
    $insurance_covered_int = $insurance_covered ? 1 : 0;
    
    $stmt->bind_param(
        "iisiddiddis", 
        $bill_id, $fee_item_id, $item_name, $quantity, $unit_price, $total_price,
        $insurance_covered_int, $insurance_amount, $self_pay_amount, $doctor_id, $department_id, $notes
    );
    
    $result = $stmt->execute();
    $stmt->close();
    
    if ($result) {
        // 更新账单总金额
        updateBillTotalAmount($bill_id);
        return true;
    }
    
    return false;
}

/**
 * 更新账单总金额
 * 
 * @param int $bill_id 账单ID
 * @return bool 成功返回true，失败返回false
 */
function updateBillTotalAmount($bill_id) {
    global $conn;
    
    $stmt = $conn->prepare("
        UPDATE medical_bills mb
        SET 
            total_amount = (SELECT COALESCE(SUM(total_price), 0) FROM medical_bill_items WHERE bill_id = ?),
            insurance_amount = (SELECT COALESCE(SUM(insurance_amount), 0) FROM medical_bill_items WHERE bill_id = ?),
            self_pay_amount = (SELECT COALESCE(SUM(self_pay_amount), 0) FROM medical_bill_items WHERE bill_id = ?)
        WHERE mb.id = ?
    ");
    
    $stmt->bind_param("iiii", $bill_id, $bill_id, $bill_id, $bill_id);
    $result = $stmt->execute();
    $stmt->close();
    
    return $result;
}

/**
 * 获取账单信息
 * 
 * @param int $bill_id 账单ID
 * @return array|null 账单信息，不存在返回null
 */
function getMedicalBill($bill_id) {
    global $conn;
    
    $stmt = $conn->prepare("
        SELECT mb.*, 
               p.name as patient_name,
               d.name as doctor_name,
               u.username as created_by_username
        FROM medical_bills mb
        LEFT JOIN patients p ON mb.patient_id = p.id
        LEFT JOIN doctors d ON mb.doctor_id = d.id
        LEFT JOIN users u ON mb.created_by = u.id
        WHERE mb.id = ?
    ");
    
    $stmt->bind_param("i", $bill_id);
    $stmt->execute();
    $result = $stmt->get_result();
    
    if ($result->num_rows > 0) {
        $bill = $result->fetch_assoc();
        $stmt->close();
        return $bill;
    }
    
    $stmt->close();
    return null;
}

/**
 * 获取账单明细项目
 * 
 * @param int $bill_id 账单ID
 * @return array 账单明细项目列表
 */
function getBillItems($bill_id) {
    global $conn;
    
    $stmt = $conn->prepare("
        SELECT mbi.*, 
               d.name as doctor_name,
               dep.name as department_name
        FROM medical_bill_items mbi
        LEFT JOIN doctors d ON mbi.doctor_id = d.id
        LEFT JOIN departments dep ON mbi.department_id = dep.id
        WHERE mbi.bill_id = ?
        ORDER BY mbi.created_at
    ");
    
    $stmt->bind_param("i", $bill_id);
    $stmt->execute();
    $result = $stmt->get_result();
    $items = [];
    
    if ($result->num_rows > 0) {
        while($row = $result->fetch_assoc()) {
            $items[] = $row;
        }
    }
    
    $stmt->close();
    return $items;
}

/**
 * 处理账单支付
 * 
 * @param int $bill_id 账单ID
 * @param float $amount 支付金额
 * @param string $payment_method 支付方式
 * @param string|null $transaction_number 交易号
 * @param string|null $notes 备注
 * @return bool 成功返回true，失败返回false
 */
function processBillPayment($bill_id, $amount, $payment_method, $transaction_number = null, $notes = null) {
    global $conn;
    
    // 获取账单信息
    $bill = getMedicalBill($bill_id);
    if (!$bill) {
        return false;
    }
    
    // 检查支付状态
    if ($bill['payment_status'] == '已支付' || $bill['payment_status'] == '已退款') {
        return false;
    }
    
    // 添加支付记录
    $stmt = $conn->prepare("
        INSERT INTO payment_records 
        (bill_id, amount, payment_method, transaction_number, notes, operator_id) 
        VALUES (?, ?, ?, ?, ?, ?)
    ");
    
    $operator_id = $_SESSION['user_id'] ?? null;
    
    $stmt->bind_param("idsssi", $bill_id, $amount, $payment_method, $transaction_number, $notes, $operator_id);
    $payment_result = $stmt->execute();
    $stmt->close();
    
    if (!$payment_result) {
        return false;
    }
    
    // 更新账单支付状态
    $total_paid = getTotalPaidAmount($bill_id);
    $total_amount = $bill['total_amount'];
    
    if ($total_paid >= $total_amount) {
        $new_status = '已支付';
    } else if ($total_paid > 0) {
        $new_status = '部分支付';
    } else {
        $new_status = '未支付';
    }
    
    $stmt = $conn->prepare("
        UPDATE medical_bills 
        SET payment_status = ?, payment_method = ?, payment_date = NOW() 
        WHERE id = ?
    ");
    
    $stmt->bind_param("ssi", $new_status, $payment_method, $bill_id);
    $update_result = $stmt->execute();
    $stmt->close();
    
    return $update_result;
}

/**
 * 获取账单已支付总金额
 * 
 * @param int $bill_id 账单ID
 * @return float 已支付总金额
 */
function getTotalPaidAmount($bill_id) {
    global $conn;
    
    $stmt = $conn->prepare("
        SELECT COALESCE(SUM(amount), 0) as total_paid 
        FROM payment_records 
        WHERE bill_id = ? AND payment_status = '成功'
    ");
    
    $stmt->bind_param("i", $bill_id);
    $stmt->execute();
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();
    $stmt->close();
    
    return (float)$row['total_paid'];
}

/**
 * 获取患者的账单列表
 * 
 * @param int $patient_id 患者ID
 * @param string|null $status 支付状态筛选
 * @param string|null $start_date 开始日期
 * @param string|null $end_date 结束日期
 * @return array 账单列表
 */
function getPatientBills($patient_id, $status = null, $start_date = null, $end_date = null) {
    global $conn;
    
    $sql = "
        SELECT mb.*, 
               p.name as patient_name,
               d.name as doctor_name
        FROM medical_bills mb
        LEFT JOIN patients p ON mb.patient_id = p.id
        LEFT JOIN doctors d ON mb.doctor_id = d.id
        WHERE mb.patient_id = ?
    ";
    
    $params = [$patient_id];
    $types = "i";
    
    if ($status) {
        $sql .= " AND mb.payment_status = ?";
        $params[] = $status;
        $types .= "s";
    }
    
    if ($start_date) {
        $sql .= " AND DATE(mb.billing_date) >= ?";
        $params[] = $start_date;
        $types .= "s";
    }
    
    if ($end_date) {
        $sql .= " AND DATE(mb.billing_date) <= ?";
        $params[] = $end_date;
        $types .= "s";
    }
    
    $sql .= " ORDER BY mb.billing_date DESC";
    
    $stmt = $conn->prepare($sql);
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    $result = $stmt->get_result();
    $bills = [];
    
    if ($result->num_rows > 0) {
        while($row = $result->fetch_assoc()) {
            $bills[] = $row;
        }
    }
    
    $stmt->close();
    return $bills;
}

/**
 * 获取医生的账单列表
 * 
 * @param int $doctor_id 医生ID
 * @param string|null $start_date 开始日期
 * @param string|null $end_date 结束日期
 * @return array 账单列表
 */
function getDoctorBills($doctor_id, $start_date = null, $end_date = null) {
    global $conn;
    
    $sql = "
        SELECT mb.*, 
               p.name as patient_name
        FROM medical_bills mb
        LEFT JOIN patients p ON mb.patient_id = p.id
        WHERE mb.doctor_id = ?
    ";
    
    $params = [$doctor_id];
    $types = "i";
    
    if ($start_date) {
        $sql .= " AND DATE(mb.billing_date) >= ?";
        $params[] = $start_date;
        $types .= "s";
    }
    
    if ($end_date) {
        $sql .= " AND DATE(mb.billing_date) <= ?";
        $params[] = $end_date;
        $types .= "s";
    }
    
    $sql .= " ORDER BY mb.billing_date DESC";
    
    $stmt = $conn->prepare($sql);
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    $result = $stmt->get_result();
    $bills = [];
    
    if ($result->num_rows > 0) {
        while($row = $result->fetch_assoc()) {
            $bills[] = $row;
        }
    }
    
    $stmt->close();
    return $bills;
}

/**
 * 生成发票号
 * 
 * @return string 发票号
 */
function generateInvoiceNumber() {
    $prefix = 'INV';
    $date = date('Ymd');
    $random = mt_rand(1000, 9999);
    return $prefix . $date . $random;
}

/**
 * 为账单生成发票
 * 
 * @param int $bill_id 账单ID
 * @return bool 成功返回true，失败返回false
 */
function generateInvoice($bill_id) {
    global $conn;
    
    // 获取账单信息
    $bill = getMedicalBill($bill_id);
    if (!$bill) {
        return false;
    }
    
    // 检查支付状态
    if ($bill['payment_status'] != '已支付') {
        return false;
    }
    
    // 检查是否已有发票
    if (!empty($bill['invoice_number'])) {
        return false;
    }
    
    // 生成发票号
    $invoice_number = generateInvoiceNumber();
    
    // 更新账单发票号
    $stmt = $conn->prepare("UPDATE medical_bills SET invoice_number = ? WHERE id = ?");
    $stmt->bind_param("si", $invoice_number, $bill_id);
    $result = $stmt->execute();
    $stmt->close();
    
    return $result;
}
?> 